package trend;

/* @Date 03 March 2008
 * @Author Hussein Patwa
 * Class for the main Local trending algorithm (Fig 7 on KDD paper)
 */

import java.util.*;
import java.lang.Double;

@SuppressWarnings("all")
public class Local {
    HashSet<ArrayList> posTrend = new HashSet(); // container for negative trends
    HashSet<ArrayList> negTrend = new HashSet(); // container for positive trends
    HashSet<ArrayList> paths;// = new HashSet();// = new HashSet(values); // set
		    // containing paths from values array (PROBLEM!)
    
    int minlength; // min length above which trend is considered established
    int maxlength; // max length above which trend is assumed
    ArrayList DATA;
    ArrayList path; // an array to hold the spatialobjects comprising the path
    
    
    class observation {
	double dist; // distance from x co-ordinate
	double diff; // distance from Y co-ordinate

	observation(double dist, double diff) {
	    this.dist = dist;
	    this.diff = diff;
	}
    }

    public Local(NeighbourhoodInfo neighbourInfo, ArrayList data, int index,
	    int minLength, int maxLength, double min_conf) {
        DATA = data;
        minlength=minLength;
        maxlength=maxLength;
	paths = computeAllPaths(neighbourInfo, index);
	System.out.println("Number of Paths: "+paths.size());
	findTrends(index, data,min_conf);
        System.out.println(posTrend.size());
        System.out.println(negTrend.size());
        
    }

    HashSet computeAllPaths(NeighbourhoodInfo neighbourInfo, int index) {
	// compute all the paths from the spatial object
	// specified by the index using the neighbourhood information
	HashSet rtn = new HashSet();
	Vector tempNeighbours = neighbourInfo.getNeighbourhoodAreaIDs(index);
	// System.out.println("index: "+index+" neighbours : "+tempNeighbours);
	for (Iterator i = tempNeighbours.iterator(); i.hasNext();) {
	    Integer node = (Integer) i.next();
	    ArrayList tempPath = new ArrayList();
            tempPath.add(new Integer(index));
	    tempPath.add(new Integer(node));
	    rtn.add(tempPath);
	    // System.out.println(tempPath);
	}
	for (int j = 0; j < minlength-1; j++)
	    rtn.addAll(extendPath(rtn, neighbourInfo));
	return rtn;
    }

    HashSet extendPath(HashSet paths, NeighbourhoodInfo neighbourInfo) {
	HashSet rtn = new HashSet();
	for (Iterator k = paths.iterator(); k.hasNext();) {
	    ArrayList path = (ArrayList) k.next();
	    int index = ((Integer) path.get(path.size() - 1)).intValue();
	    Vector tempNeighbours = neighbourInfo
		    .getNeighbourhoodAreaIDs(index);
	    // System.out.println("index: "+index+" neighbours :
	    // "+tempNeighbours);
	    for (Iterator i = tempNeighbours.iterator(); i.hasNext();) {
		Integer node = (Integer) i.next();
		if (!path.contains(node)) {
		    ArrayList tempPath = new ArrayList();
		    tempPath.addAll(path);
		    tempPath.add(node);
		    rtn.add(tempPath);
		    // System.out.println(tempPath);
		}
	    }
	}
	return rtn;
    }

    public void findTrends(int index, ArrayList data,double min_conf) {
	for (Iterator i = paths.iterator(); i.hasNext();) {
	    path = (ArrayList) i.next(); // Move first element of paths to
					    // path
	    //System.out.println(path.size());
            if((path.size()>=minlength)){//&&(path.size()<=maxlength)){
            TreeMap PathObs = new TreeMap();
	    for (int j = 0; j < path.size(); j++) // initialise
							    // counter that will
							    // track through the
							    // colums of the set
							    // paths
	    {
		
		Integer currentIndex = (Integer) path.get(j);
		Spatialobject o = (Spatialobject) data.get(index);
		Spatialobject object = (Spatialobject) data.get(currentIndex);
		double dist = Math.sqrt(Math.pow((object.getX() - o.getX()), 2)
			+ Math.pow((object.getY() - o.getY()), 2)); // calculate
								    // the
								    // difference
								    // in the x
								    // co-ordinate
		double diff = object.getV() - o.getV(); // calculate the
							// difference in the y
							// co-ordinate
		// observation obsTemp = new observation(dist,diff); // insert
		// distX into observations
		PathObs.put(dist, diff);// insert distY into observations
            }
            if(PathObs.size()>0){
                Regression reg = new Regression(PathObs);

                    // Correlation
                Correlation corr = new Correlation(PathObs);
                double cor = corr.getCorrelationCoefficient();

                    if(Math.abs(cor)>min_conf){
                        System.out.println("PathObs: "+PathObs);
                        System.out.println("Cor: "+cor);
                        if(cor > 0) // Insert the path into the set posTrend or negTrend
                        {
                            posTrend.add(path);
                        }
                        else if(cor < 0)
                        {
                            negTrend.add(path);
                        }
                    }
            }
	}
        }
    }
    
    
    // Method to show pos or neg trend set
    public void viewTrends() {
        for(ArrayList<Integer> p:posTrend){
            //print area names from each path
            for(Integer index:p){
                Spatialobject o = (Spatialobject)DATA.get(index);
                System.out.print(o.getName()+" ");
            }
            System.out.println();
        }
        for(ArrayList<Integer> n:negTrend){
            //print area names from each path
            for(Integer index:n){
                Spatialobject o = (Spatialobject)DATA.get(index);
                System.out.print(o.getName()+" ");
            }
            System.out.println();
        }
    }

}
